home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 12 - 1996 / 12.12 Dec 96 / Flat File Databases / Invoice Example ƒ / Functional ƒ / CustomerFuncs.c next >
Encoding:
Text File  |  1996-03-02  |  13.5 KB  |  472 lines  |  [TEXT/CWIE]

  1. //handle customer window stuff.
  2. #include "InvoiceGlobals.h"
  3. #include "BTreeDef.h"
  4. #include "BTreeProtos.h"
  5. #include "SampleHeader.h"
  6. #include "Actions.h"
  7.  
  8. //some vars local to this file
  9. static short     itemType;
  10. static Handle    item;
  11. static Rect     box;
  12. static Str255    itemString;
  13. static short    ScratchShort;
  14. static long        ScratchLong;
  15. //FindType = 1 means by num, 2 by name
  16. // these variables are used in searches
  17. Str255    SearchNameP;
  18. Str255    FoundNameP;
  19. long    SearchNumP;
  20. long    FoundNumP;
  21. FileAddr    CurrentCustomerAddr;
  22. short     gCustomerFindType = kFindByName;
  23.  
  24. #define kPopUp 6
  25. #define kDoIt 1
  26.  
  27. //three utility functions; makes life much easier
  28.  
  29. void GetFromCustDialog(void);
  30. void PutToCustDialog(void);
  31. short RetrieveString (void);
  32.  
  33.  
  34. //the heart of the matter
  35.  
  36. short FindCustByNumber(void);
  37. short FindCustByName(void);
  38. short CustFindNextPrev(short direction);
  39. short CustInsert(void);
  40. short CustEdit(void);
  41. short CustDelete(void);
  42.  
  43.  
  44.  
  45. //this code is used repeatedly.  Transfers information from the 
  46. //dialogs to the "current record" and vice versa
  47.  
  48. void GetFromCustDialog(void){
  49.     //cust name id = 3
  50.     //cust num id = 2
  51.     //cust string id = 7
  52.     GetDialogItem(gCustomerDialog, 3, &itemType, &item, &box);
  53.     GetDialogItemText(item, itemString);
  54.     ScratchShort = (short)itemString[0];
  55.     if (ScratchShort>31)
  56.         ScratchShort = 31;
  57.     BlockMove(itemString,gCustomer.CustName, ScratchShort+1);
  58.     GetDialogItem(gCustomerDialog, 2, &itemType, &item, &box);
  59.     GetDialogItemText(item, itemString);
  60.     StringToNum(itemString,&ScratchLong);
  61.     gCustomer.CustNo = ScratchLong;
  62.     GetDialogItem(gCustomerDialog, 7, &itemType, &item, &box);
  63.     GetDialogItemText(item, itemString);
  64.     ScratchShort = (short)itemString[0];
  65.     if (ScratchShort>39)
  66.         ScratchShort = 39;
  67.     BlockMove(itemString,gCustString,ScratchShort + 1);
  68.     }
  69.  
  70. void PutToCustDialog(void){
  71.     //cust name id = 3
  72.     //cust num id = 2
  73.     //Custstring id = 7
  74.     GrafPtr    oldPort;
  75.     GetPort(&oldPort);
  76.     SetPort((GrafPtr)gCustomerDialog);
  77.     GetDialogItem(gCustomerDialog, 3, &itemType, &item, &box);
  78.     ScratchShort = (short)(gCustomer.CustName[0]);
  79.     if (ScratchShort>31)
  80.         ScratchShort = 31;
  81.     BlockMove(gCustomer.CustName,itemString, ScratchShort+1);
  82.     SetDialogItemText(item, itemString);
  83.     SetDialogItem(gCustomerDialog, 3, itemType, item, &box);
  84.     InvalThisItemRect(gCustomerDialog,3);
  85.     GetDialogItem(gCustomerDialog, 2, &itemType, &item, &box);
  86.     ScratchLong = gCustomer.CustNo;
  87.     NumToString(ScratchLong,itemString);
  88.     SetDialogItemText(item, itemString);
  89.     SetDialogItem(gCustomerDialog, 2, itemType, item, &box);
  90.     InvalThisItemRect(gCustomerDialog,2);
  91.     GetDialogItem(gCustomerDialog, 7, &itemType, &item, &box);
  92.     ScratchShort = (short)(gCustString[0]);
  93.     if (ScratchShort>39)
  94.         ScratchShort = 39;
  95.     BlockMove(gCustString,itemString, ScratchShort+1);
  96.     SetDialogItemText(item, itemString);
  97.     SetDialogItem(gCustomerDialog, 7, itemType, item, &box);
  98.     InvalThisItemRect(gCustomerDialog,7);
  99.     BeginUpdate(gCustomerDialog);
  100.     DrawDialog(gCustomerDialog);
  101.     EndUpdate(gCustomerDialog);
  102.     SetPort(oldPort);
  103.     }
  104. // generic error handler; simply puts up an alert if called.    
  105. void HandleErrorMsg(short theErr){
  106.         short     AlertReturn;
  107.         long    ErrorLong;
  108.         Str255    ErrorString;
  109.         ErrorLong = theErr;
  110.         NumToString(ErrorLong, ErrorString);
  111.         ParamText(ErrorString, "\p", "\p", "\p");
  112.         AlertReturn = StopAlert(129, NULL);
  113.     }
  114.  
  115. //another utility function    
  116. short RetrieveString (void){
  117.     short StringErr;
  118.     StringErr = Read_Data(gInvoiceFCH,kCustStringSize,gCustomer.StringAddr,(Ptr)gCustString);
  119.     }
  120.  
  121. //these two functions could easily be made into one
  122. //do it in two for demonstrative purposes
  123. short FindCustByNumber(void){
  124.     short     FindErr= noErr;
  125.     short     StringSize;
  126.     FileAddr foundAddr;
  127. // get data
  128.     GetFromCustDialog();
  129. // set up search
  130.     SearchNumP = gCustomer.CustNo;
  131.     gCustomerFindType = kFindByNumber;
  132. // find on customer no. in Customer number tree
  133.     FindErr = Find_Equal(kCustomerNumTree,gInvoiceFCH,(Ptr)&SearchNumP,(Ptr)&FoundNumP,&foundAddr,kLongCompare);
  134.     if (FindErr != noErr) {
  135.             HandleErrorMsg(FindErr);
  136.             return FindErr;
  137.         };
  138. // read the data in from the address that was passed to &foundAddr
  139.     FindErr = Read_Data(gInvoiceFCH, kCustomerSize,foundAddr,(Ptr)&gCustomer);
  140.     if (FindErr != noErr) {
  141.             HandleErrorMsg(FindErr);
  142.             return FindErr;
  143.         };
  144. // pull in the child record
  145.     FindErr = RetrieveString();
  146.     if (FindErr != noErr) {
  147.             HandleErrorMsg(FindErr);
  148.             return FindErr;
  149.         };
  150. // update the display
  151.     PutToCustDialog();
  152. // set up the variables that will survive across function calls.
  153.     SearchNumP = FoundNumP;
  154.     CurrentCustomerAddr = foundAddr;
  155.     return FindErr;
  156. }
  157.  
  158. // see find by number above; this is very similar code.
  159. short FindCustByName(void){
  160.     short     FindErr= noErr;
  161.     short     StringSize;
  162.     FileAddr foundAddr;
  163.  
  164.     GetFromCustDialog();
  165.     StringSize = gCustomer.CustName[0];
  166.     if (StringSize>31)
  167.         StringSize = 31;
  168.     BlockMove((Ptr)gCustomer.CustName,(Ptr)SearchNameP,StringSize+1);
  169.     gCustomerFindType = kFindByName;
  170.     FindErr = Find_Equal(kCustomerNameTree,gInvoiceFCH,(Ptr)SearchNameP,(Ptr)FoundNameP,&foundAddr,kPStringCompare);
  171.     if (FindErr != noErr) {
  172.             HandleErrorMsg(FindErr);
  173.             return FindErr;
  174.         };
  175.     FindErr = Read_Data(gInvoiceFCH, kCustomerSize,foundAddr,(Ptr)&gCustomer);
  176.     if (FindErr != noErr) {
  177.             HandleErrorMsg(FindErr);
  178.             return FindErr;
  179.         };
  180.     FindErr = RetrieveString();
  181.     if (FindErr != noErr) {
  182.             HandleErrorMsg(FindErr);
  183.             return FindErr;
  184.         };
  185.     PutToCustDialog();
  186.     BlockMove((Ptr)FoundNameP,(Ptr)SearchNameP, 256);;
  187.     CurrentCustomerAddr = foundAddr;
  188.     return FindErr;
  189. }
  190.  
  191. short CustFindNextPrev(short direction){
  192.     short FindErr = noErr;
  193.     FileAddr foundAddr;
  194.     FileAddr prevAddr;
  195.     short    TreeNo;
  196.     Ptr        SearchP;
  197.     Ptr        FoundP;
  198.     CompareProcPtr Comparison;
  199.     
  200.     if (gCustomerFindType == kFindByNumber) {
  201.         SearchP = (Ptr)&SearchNumP;
  202.         FoundP    = (Ptr)&FoundNumP;
  203.         TreeNo = kCustomerNumTree;
  204.         Comparison = kLongCompare;
  205.         prevAddr = CurrentCustomerAddr;
  206.     }
  207.     else {
  208.         SearchP = (Ptr)SearchNameP;
  209.         FoundP = (Ptr)FoundNameP;
  210.         TreeNo = kCustomerNameTree;
  211.         Comparison = kPStringCompare;
  212.         prevAddr = CurrentCustomerAddr;
  213.     };
  214.     
  215.     if (direction == kNext) 
  216.         FindErr = Find_Next(TreeNo, gInvoiceFCH, SearchP, prevAddr, FoundP, &foundAddr, Comparison);
  217.     else
  218.         FindErr = Find_Previous(TreeNo, gInvoiceFCH, SearchP, prevAddr, FoundP, &foundAddr, Comparison);
  219.     if (FindErr != noErr) {
  220.             HandleErrorMsg(FindErr);
  221.             return FindErr;
  222.     };
  223.     FindErr = Read_Data(gInvoiceFCH, kCustomerSize,foundAddr,(Ptr)&gCustomer);
  224.     if (FindErr != noErr) {
  225.             HandleErrorMsg(FindErr);
  226.             return FindErr;
  227.         };
  228.     FindErr = RetrieveString();
  229.     if (FindErr != noErr) {
  230.             HandleErrorMsg(FindErr);
  231.             return FindErr;
  232.         };
  233.     PutToCustDialog();
  234.     if (gCustomerFindType == kFindByNumber) {
  235.         CurrentCustomerAddr = foundAddr;
  236.         SearchNumP = FoundNumP;
  237.         }
  238.     else {
  239.         CurrentCustomerAddr = foundAddr;
  240.         BlockMove((Ptr)FoundNameP, (Ptr)SearchNameP, 256);
  241.         }
  242.     return FindErr;                
  243. }
  244.  
  245. short CustInsert(void) {
  246.     short     InsertErr = noErr;
  247.     FileAddr    InsertAddr;
  248.     short    AlertReturn;
  249.     short    StringSize;    
  250.     //first,check and make sure that the proposed ID number is not in the tree
  251.     GetFromCustDialog();
  252.     SearchNumP = gCustomer.CustNo;
  253.     InsertErr = Find_Equal(kCustomerNumTree,gInvoiceFCH,(Ptr)&SearchNumP,(Ptr)&FoundNumP,&InsertAddr,kLongCompare);
  254.     if (SearchNumP == FoundNumP) {
  255.         AlertReturn = CautionAlert(130, NULL);
  256.         InsertErr = paramErr;
  257.         return paramErr;
  258.         };
  259.     //get file space
  260.     // ***must insert the child record first!!!
  261.     InsertErr = Get_Bytes(gInvoiceFCH, &InsertAddr, kCustStringSize);
  262.     if (InsertErr != noErr) {
  263.         HandleErrorMsg(InsertErr);
  264.         return InsertErr;
  265.         };
  266.     //write the child data
  267.     InsertErr = Write_Data(gInvoiceFCH, kCustStringSize,InsertAddr, (Ptr)gCustString);
  268.     if (InsertErr != noErr) {
  269.         HandleErrorMsg(InsertErr);
  270.         return InsertErr;
  271.         };
  272.     //put the child address into the parent record
  273.     gCustomer.StringAddr = InsertAddr;
  274.     //now insert the parent record
  275.     InsertErr = Get_Bytes(gInvoiceFCH, &InsertAddr, kCustomerSize);
  276.     if (InsertErr != noErr) {
  277.         HandleErrorMsg(InsertErr);
  278.         return InsertErr;
  279.         };
  280.     //write the record to file
  281.     InsertErr = Write_Data(gInvoiceFCH, kCustomerSize, InsertAddr, (Ptr)&gCustomer);
  282.     if (InsertErr != noErr) {
  283.         HandleErrorMsg(InsertErr);
  284.         return InsertErr;
  285.         };
  286.     //insert the keys
  287.     InsertErr = Insert_Key(kCustomerNumTree, kUniqueKeys, gInvoiceFCH,(Ptr)&SearchNumP, InsertAddr, kLongCompare);
  288.     if (InsertErr != noErr) {
  289.         HandleErrorMsg(InsertErr);
  290.         return InsertErr;
  291.         // if for real, should also delete the record and release file space if failed insertion
  292.         };
  293.     StringSize = gCustomer.CustName[0];
  294.     if (StringSize>31)
  295.         StringSize = 31;
  296.     BlockMove((Ptr)gCustomer.CustName,(Ptr)SearchNameP,StringSize+1);
  297.     InsertErr = Insert_Key(kCustomerNameTree, kDuplicateKeys, gInvoiceFCH,(Ptr)&SearchNameP, InsertAddr, kPStringCompare);
  298.     if (InsertErr != noErr) {
  299.         HandleErrorMsg(InsertErr);
  300.         return InsertErr;
  301.         // if for real, should also delete the record and release file space if failed insertion
  302.         };
  303.     CurrentCustomerAddr = InsertAddr;
  304.     
  305.     return InsertErr;
  306. }
  307.  
  308. short CustEdit(void) {
  309.     short         EditErr = noErr;
  310.     short         AlertReturn;
  311.     FileAddr    EditAddr;
  312.     //the record in the "main buffer" should be moved to a secondary buffer
  313.     //the child record **in this case** doesn't need to be protected
  314.     CustomerType    CustomerEdit;
  315.     
  316.     BlockMove(&gCustomer,&CustomerEdit,kCustomerSize);
  317.     GetFromCustDialog();
  318.     // to protect data integrity, the ID # cannot be edited
  319.     // thus, only the strings need to be compared.
  320.     // more complex approach would be needed in real app
  321.     // if strings different, insert new record, edit the key string
  322.     if (!EqualString(gCustomer.CustName, CustomerEdit.CustName, TRUE, FALSE)) {
  323.         EditAddr = CurrentCustomerAddr;
  324.         //overwrite the old data
  325.         EditErr = Write_Data(gInvoiceFCH, kCustomerSize, EditAddr, (Ptr)&gCustomer);
  326.         if (EditErr != noErr) {
  327.             HandleErrorMsg(EditErr);
  328.             return EditErr;
  329.             };
  330.         EditErr = Write_Data(gInvoiceFCH,kCustStringSize,CustomerEdit.StringAddr,(Ptr)gCustString);
  331.         //Very Important. Delete the old key
  332.         EditErr = Delete_Key(kCustomerNameTree,kDuplicateKeys, gInvoiceFCH, (Ptr)CustomerEdit.CustName, &EditAddr, kPStringCompare);
  333.         if (EditErr != noErr) {
  334.             HandleErrorMsg(EditErr);
  335.             return EditErr;
  336.             };
  337.         //Insert the new Key
  338.         EditErr = Insert_Key(kCustomerNameTree, kDuplicateKeys, gInvoiceFCH,(Ptr)gCustomer.CustName, EditAddr, kPStringCompare);
  339.         if (EditErr != noErr) {
  340.             HandleErrorMsg(EditErr);
  341.             return EditErr;
  342.             };
  343.     };
  344.     BlockMove((Ptr)gCustomer.CustName,(Ptr)SearchNameP,256);
  345.     CurrentCustomerAddr = EditAddr;
  346.     return EditErr;
  347. }
  348.  
  349. short CustDelete(void) {
  350.     short         DeleteErr = noErr;
  351.     short         AlertReturn;
  352.     FileAddr    DeleteAddr;
  353.     //assumes that a found, insert, edit done so there is a current record in buffer.
  354.     DeleteAddr = CurrentCustomerAddr;
  355.     //release keys first.  better to have orphan record than keys pointing to nowhere
  356.     DeleteErr = Delete_Key(kCustomerNameTree,kDuplicateKeys, gInvoiceFCH, (Ptr)gCustomer.CustName, &DeleteAddr, kPStringCompare);
  357.     if (DeleteErr != noErr) {
  358.         HandleErrorMsg(DeleteErr);
  359.         return DeleteErr;
  360.         };
  361.     DeleteErr = Delete_Key(kCustomerNumTree,kUniqueKeys, gInvoiceFCH, (Ptr)gCustomer.CustNo, &DeleteAddr, kLongCompare);
  362.     if (DeleteErr != noErr) {
  363.         HandleErrorMsg(DeleteErr);
  364.         return DeleteErr;
  365.         };
  366.     //release space in file
  367.     //release child record first
  368.     DeleteErr = Release_Bytes(gInvoiceFCH, gCustomer.StringAddr, kCustStringSize);
  369.     if (DeleteErr != noErr) {
  370.         HandleErrorMsg(DeleteErr);
  371.         return DeleteErr;
  372.         };
  373. // now release the customer rec itself
  374.     DeleteErr = Release_Bytes(gInvoiceFCH, DeleteAddr, kCustomerSize);
  375.     if (DeleteErr != noErr) {
  376.         HandleErrorMsg(DeleteErr);
  377.         return DeleteErr;
  378.         };
  379.     CurrentCustomerAddr = noAddr;
  380.     gCustomer.CustName[0] = 0;
  381.     gCustomer.CustNo = 0;
  382.     PutToCustDialog();
  383.     return DeleteErr;
  384. }
  385. // handles input from the modeless dialog
  386. void HandleCustomerAction(EventRecord *theEvent, short *theItem){
  387.     short CustomerErr;
  388.     ControlHandle popControl;
  389.     short popValue;
  390.     short itemNo = 2;
  391.     short itemType;
  392.     Handle item;
  393.     Rect box;
  394.     Boolean IsEditText = FALSE;
  395.     
  396.     switch (*theItem) {
  397.         case kPopUp:
  398.         popControl = GetCtlHandle(gCustomerDialog,kPopUp);
  399.         popValue = GetControlValue(popControl);
  400.         
  401.         GetDialogItem(gCustomerDialog, itemNo, &itemType, &item, &box);
  402.         if (itemType == editText)
  403.             IsEditText = TRUE;
  404.         switch (popValue) {
  405.             case kFindByName:
  406.             gCustomerAction = kFindByName;
  407.             itemType = editText;
  408.             break;
  409.             case kFindByNumber:
  410.             gCustomerAction = kFindByNumber;
  411.             itemType = editText;
  412.             break;
  413.             case kNext:
  414.             gCustomerAction = kNext;
  415.             itemType = editText;
  416.             break;
  417.             case kPrevious:
  418.             gCustomerAction = kPrevious;
  419.             itemType = editText;
  420.             break;
  421.             case kInsert:
  422.             gCustomerAction =kInsert;
  423.             itemType = editText;
  424.             break;
  425.             case kEdit:
  426.             gCustomerAction = kEdit;
  427.             itemType = statText;
  428.             break;
  429.             case kDelete:
  430.             gCustomerAction = kDelete;
  431.             break;
  432.         };//popup value switch
  433.         if ((!IsEditText && (itemType == editText))||(IsEditText && (itemType == statText))) {
  434.             // not gorgeous, but it works
  435.             SetDialogItem(gCustomerDialog, itemNo, itemType, item, &box);
  436.             InsetRect(&box, -5, -5);
  437.             EraseRect(&box);
  438.             InvalThisItemRect(gCustomerDialog,itemNo);
  439.             SelectDialogItemText(gCustomerDialog, 3, 0, 0);
  440.             BeginUpdate(gCustomerDialog);
  441.             DrawDialog(gCustomerDialog);
  442.             EndUpdate(gCustomerDialog);
  443.             };
  444.         break; //popup
  445.         
  446.         case kDoIt:
  447.         switch (gCustomerAction) {
  448.             case kFindByName:
  449.             CustomerErr = FindCustByName();
  450.             break;
  451.             case kFindByNumber:
  452.             CustomerErr = FindCustByNumber();
  453.             break;
  454.             case kNext:
  455.             CustomerErr = CustFindNextPrev(kNext);
  456.             break;
  457.             case kPrevious:
  458.             CustomerErr = CustFindNextPrev(kPrevious);
  459.             break;
  460.             case kInsert:
  461.             CustomerErr =CustInsert();
  462.             break;
  463.             case kEdit:
  464.             CustomerErr = CustEdit();
  465.             break;
  466.             case kDelete:
  467.             CustomerErr = CustDelete();
  468.             break;
  469.         };//gCustomerAction switch
  470.         break;
  471.     }//switch
  472. }//function